package com.example.concurrentprogramming8016.AQS;


import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

/**
 * @author liyanhao
 * @Date 2023-01-05 10:50
 * 这里是一个不可重入的互斥锁类，使用值0表示解锁状态，
 * 1表示锁定状态。虽然不可重入锁并不严格要求记录当前所有者线程，
 * 但此类无论如何都会这样做，以便更容易监控使用情况。
 * 它还支持条件并公开其中一种检测方法：
 */
public class Mutx implements Lock, java.io.Serializable {

    //our internal helper class
    private static class Sync extends AbstractQueuedSynchronizer {
        //如果同步仅针对当前（调用）线程保持，则返回true 。
        // 每次调用非等待AbstractQueuedSynchronizer.ConditionObject方法时都会调用此方法。
        // （等待方法改为调用release 。）
        @Override
        protected boolean isHeldExclusively() {
            return getState() == 1;
        }

        public boolean tryAcquire(int aquires) {
            //断言false终止执行
            assert aquires == 1;
            if (compareAndSetState(0, 1)) {
                //设置当前拥有独占访问权限
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }

        protected boolean tryRelease(int release) {
            assert release == 1;
            if (getState() == 0) {
                throw new IllegalMonitorStateException();
            }
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }

        Condition newCondition() {
            return new ConditionObject();
        }

        private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
            s.defaultReadObject();
            setState(0);
        }
    }

    Sync sync = new Sync();

    @Override

    public void lock() {
        sync.acquire(1);
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }

    @Override
    public boolean tryLock() {
        return sync.tryAcquire(1);
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return sync.tryAcquireNanos(1, unit.toNanos(time));
    }

    @Override
    public void unlock() {
        sync.release(1);
    }

    @Override
    public Condition newCondition() {
        return sync.newCondition();
    }

    public boolean isLock() {
        return sync.isHeldExclusively();
    }

    public boolean hasQueuedTreads() {
        return sync.hasQueuedThreads();
    }


}
